import _ from "lodash";
import fs from 'fs-extra';
import path from "path";
import { findOption, replaceOrThrow } from "../../tools/vendor.js";
import { BaseTask, TaskResult } from "./BastTask.js";
import { toolchain } from "../../toolchain.js";
import { CommonEnv } from "../CommonEnv.js";
import { ignoreSVN } from "../../CommonAction.js";
import { I18NOut } from "../I18N.js";

export declare interface I18NResult {
    out: I18NOut | null
}

export class I18NTask extends BaseTask<I18NResult> {
    async run(): Promise<TaskResult<I18NResult>> {
        console.time('本地化');
        const out = await this._prepare_localize_res();
        console.timeEnd('本地化');
        
        return { success: true, errorCode: 0, data: { out } };
    }

    private async _prepare_localize_res(): Promise<I18NOut | null> {
        const out = await toolchain.i18n.runI18N(this.cmdOption, 'R');
        if (out == null) return null;
        const langs = findOption(out.localizeParams, '--langs');
        console.log('--langs:', langs);
        if (langs) {
            const langArr = langs.split(',');
            // 拷贝PlayerNameM.XX.json
            for (const lang of langArr) {
                for (const lang2 of langArr) {
                    const src = path.join(toolchain.params.workSpacePath, 'Assets/AssetSources/data', `PlayerNameM.${lang2}.json`);
                    const dst = path.join(toolchain.params.workSpacePath, `Assets/AssetSources/data${lang}`, `PlayerNameM.${lang2}.json`);
                    await fs.copyFile(src, dst);
                }
            }
            // 忽略翻译文件夹
            let ignoreList: string[] = [];
            for (const lang of langArr) {
                const dataLang = `Assets/AssetSources/data${lang}`;
                ignoreList.push(dataLang);
                const bjsondataLang = `Assets/AssetSources/bjsondata${lang}`;
                ignoreList.push(bjsondataLang);
            }
            if (ignoreList.length > 0) {
                await ignoreSVN(toolchain.params.workSpacePath, ignoreList);
            }

            // 更新i18n.ts中的语言信息
            const langMap: { [gameid: number]: string[] } = {};
            const allCfgs = toolchain.platformCfgParser.getAll();
            const allLangs: string[] = [];
            allCfgs?.forEach((v) => {
                if (v['localize-params']) {
                    const langs = findOption(v['localize-params'].split(/\s+/), '--langs');
                    if (langs != null) {
                        const langArr = langs.split(',');
                        // CN是默认支持的
                        if (!langArr.includes('CN')) langArr.unshift('CN');
                        langMap[v.gameid] = langArr;
                        allLangs.push(...langArr);
                    }
                }
            });
            const i18nts = path.join(toolchain.params.workSpacePath, 'TsScripts/System/i18n/i18n.ts');
            const i18ntsContent = await fs.readFile(i18nts, 'utf-8');
            const langsDef = Array.from(new Set(allLangs)).map((v) => `'${v}'`).join(' | ');
            console.log('update langs definition in i18n.ts:', langsDef);
            let newI18ntsContent = replaceOrThrow(i18ntsContent, /(?<=export declare type Langs = ).+(?=;)/, langsDef);
            console.log('update lang map in i18n.ts:', JSON.stringify(langMap, null, 2));
            newI18ntsContent = replaceOrThrow(newI18ntsContent, /(?<=_supportLangsMap: \{ \[gameid: number\]: Langs\[\] \} = ).+(?=;)/, JSON.stringify(langMap));
            await fs.writeFile(i18nts, newI18ntsContent, 'utf-8');
        }
        // 如果配置了固定语言，则修改为不可切换
        const fixedLang = toolchain.params.channelCfg['localize-fixed-lang'];
        if (fixedLang) {
            console.log('set fixed lang:', fixedLang);
            const i18nCS = path.join(toolchain.params.workSpacePath, CommonEnv.I18N_CS);
            const i18nCSContent = await fs.readFile(i18nCS, 'utf-8');
            const newI18nCSContent = i18nCSContent.replace('Switchable = true', 'Switchable = false').replace(/(?<=DefaultLang = ")\w+(?=")/, fixedLang);
            await fs.writeFile(i18nCS, newI18nCSContent, 'utf-8');
        }
        // 设置默认语言，localize-fixed-lang优先级高于localize-default-lang
        const defaultLang = fixedLang || toolchain.params.channelCfg['localize-default-lang'] || 'CN';
        await this.modifyLangCfg(langs, defaultLang, CommonEnv.Root_Unity);
        await this.modifyLangCfg(langs, defaultLang, CommonEnv.Root_webgl_Unity);
        return out;
    }

    private async modifyLangCfg(langs: string | null, defaultLang: string, file: string): Promise<void> {
        const rootFile = path.join(toolchain.params.workSpacePath, file);
        if (!fs.existsSync(rootFile)) return;
        const rootContent = await fs.readFile(rootFile, 'utf-8');
        let newRootContent = rootContent;
        if (defaultLang) {
            console.log('set default lang:', defaultLang);
            newRootContent = newRootContent.replace(/(?<=DefaultGameLang: )\w+/, defaultLang);
        }
        if (newRootContent != rootContent) {
            console.log(`Update lang cfg successfully: ${file}`);
            await fs.writeFile(rootFile, newRootContent, 'utf-8');
        }
    }
}
